﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AccelerateSensor.Database.Tools;
using Vibrant.InfluxDB.Client;

namespace AccelerateSensor.Database.InfluxDb
{
    public class InfluxDbHelper
    {
        private readonly InfluxClient _influxClient;
        private string _databaseName;

        public InfluxDbHelper(string influxHost, string username, string password)
        {
            _influxClient = new InfluxClient(new Uri(influxHost), username, password);
        }

        #region Init

        public void Init(string databaseName)
        {
            InitAsync(databaseName).GetAwaiter();
        }

        private async Task InitAsync(string databaseName)
        {
            //创建数据库
            _databaseName = databaseName;
            await _influxClient.CreateDatabaseAsync(_databaseName);
        }

        #endregion

        #region AddData

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <typeparam name="TInfluxData">泛型数据类型</typeparam>
        /// <param name="measurementName">表名称</param>
        /// <param name="dataArray">数据数组</param>
        /// <param name="databaseName">数据库名称(可选)</param>
        public void AddData<TInfluxData>(string measurementName, TInfluxData[] dataArray, string databaseName = "")
            where TInfluxData : new()
        {
            AddDataAsync(databaseName, measurementName, dataArray).GetAwaiter();
        }

        private async Task AddDataAsync<TInfluxData>(
            string databaseName, string measurementName,
            TInfluxData[] dataArray) where TInfluxData : new()
        {
            try
            {
                databaseName = string.IsNullOrWhiteSpace(databaseName) ? _databaseName : databaseName;
                await _influxClient.WriteAsync(databaseName, measurementName, dataArray);
            }
            catch (Exception e)
            {
                LogHelper.AddErrorLog(e.Message);
            }
        }

        #endregion

        /// <summary>
        /// 获取数据个数
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="databaseName">数据库名称(可选)</param>
        /// <returns>数据个数</returns>
        public async Task<int> GetDataCountAsync(string query, string databaseName = "")
        {
            try
            {
                databaseName = string.IsNullOrWhiteSpace(databaseName) ? _databaseName : databaseName;
                var resultSet = await _influxClient.ReadAsync<CountInfo>(databaseName, query);

                // resultSet will contain 1 result in the Results collection (or multiple if you execute multiple queries at once)
                var result = resultSet.Results[0];
                if (!result.Succeeded)
                {
                    LogHelper.AddErrorLog(result.ErrorMessage);
                    return 0;
                }

                // result will contain 1 series in the Series collection (or potentially multiple if you specify a GROUP BY clause)
                var series = result.Series[0];
                return series.Rows[0].Count;
            }
            catch (Exception e)
            {
                LogHelper.AddErrorLog(e.Message);
                return 0;
            }
        }

        /// <summary>
        /// 异步获取数据
        /// </summary>
        /// <typeparam name="TInfluxData">数据类型</typeparam>
        /// <param name="query">查询条件</param>
        /// <param name="databaseName">数据库名称(可选)</param>
        /// <returns>数据集合</returns>
        public async Task<List<TInfluxData>> GetDataAsync<TInfluxData>(string query, string databaseName = "")
            where TInfluxData : new()
        {
            try
            {
                databaseName = string.IsNullOrWhiteSpace(databaseName) ? _databaseName : databaseName;
                var resultSet = await _influxClient.ReadAsync<TInfluxData>(databaseName, query);

                // resultSet will contain 1 result in the Results collection (or multiple if you execute multiple queries at once)
                var result = resultSet.Results[0];
                if (!result.Succeeded)
                {
                    LogHelper.AddErrorLog(result.ErrorMessage);
                    return new List<TInfluxData>();
                }

                // result will contain 1 series in the Series collection (or potentially multiple if you specify a GROUP BY clause)
                var series = result.Series[0];

                var dataList = new List<TInfluxData>();
                dataList.AddRange(series.Rows);
                return dataList;
            }
            catch (Exception e)
            {
                LogHelper.AddErrorLog(e.Message);
                return new List<TInfluxData>();
            }
        }

        /// <summary>
        /// 获取表数据个数的辅助类
        /// </summary>
        private class CountInfo
        {
            [InfluxTimestamp]
            // ReSharper disable once UnusedMember.Local
            public DateTime Timestamp { get; set; }

            [InfluxField("count")]
            // ReSharper disable once UnusedAutoPropertyAccessor.Local
            public int Count { get; set; }
        }
    }
}
